/**
 * 统一文件上传API
 * 基于工厂+策略模式设计的统一文件上传系统
 */

import { http } from "@/utils/http";

// ==================== 类型定义 ====================

/** API响应基础结构 */
export interface ApiResponse<T = any> {
  code: number;
  message: string;
  data: T;
  timestamp: number;
}

/** 文件上传结果 */
export interface UnifiedFileUploadResult {
  /** 文件名 */
  fileName: string;
  /** 原始文件名 */
  originalFileName: string;
  /** 文件大小（字节） */
  fileSize: number;
  /** 文件类型 */
  contentType: string;
  /** 相对路径 */
  relativePath: string;
  /** 文件访问URL */
  fileUrl: string;
  /** 上传时间戳 */
  uploadTime: number;
}

/** 文件类型枚举 */
export enum FileUploadType {
  /** 用户头像 */
  AVATAR = "avatar",
  /** 文章封面 */
  ARTICLE_COVER = "article_cover",
  /** 评论图片 */
  COMMENT_IMAGE = "comment_image",
  /** 通用图片 */
  GENERAL_IMAGE = "general_image"
}

/** 文件验证结果 */
export interface FileValidationResult {
  /** 是否有效 */
  valid: boolean;
  /** 错误信息 */
  message?: string;
}

// ==================== API接口函数 ====================

/**
 * 统一文件上传接口
 * @param file 要上传的文件
 * @param type 文件类型
 * @returns Promise<ApiResponse<UnifiedFileUploadResult>>
 */
export const unifiedFileUploadApi = (
  file: File,
  type: FileUploadType
): Promise<ApiResponse<UnifiedFileUploadResult>> => {
  const formData = new FormData();
  formData.append("file", file);
  formData.append("type", type);

  return http.request<ApiResponse<UnifiedFileUploadResult>>(
    "post",
    "/api/upload/unified",
    {
      data: formData,
      headers: {
        "Content-Type": "multipart/form-data"
      }
    }
  );
};

/**
 * 上传文章封面
 * @param file 要上传的文件
 * @returns Promise<ApiResponse<UnifiedFileUploadResult>>
 */
export const uploadArticleCoverApi = (
  file: File
): Promise<ApiResponse<UnifiedFileUploadResult>> => {
  const formData = new FormData();
  formData.append("file", file);

  return http.request<ApiResponse<UnifiedFileUploadResult>>(
    "post",
    "/api/upload/article-cover",
    {
      data: formData,
      headers: {
        "Content-Type": "multipart/form-data"
      }
    }
  );
};

/**
 * 上传评论图片
 * @param file 要上传的文件
 * @returns Promise<ApiResponse<UnifiedFileUploadResult>>
 */
export const uploadCommentImageApi = (
  file: File
): Promise<ApiResponse<UnifiedFileUploadResult>> => {
  const formData = new FormData();
  formData.append("file", file);

  return http.request<ApiResponse<UnifiedFileUploadResult>>(
    "post",
    "/api/upload/comment-image",
    {
      data: formData,
      headers: {
        "Content-Type": "multipart/form-data"
      }
    }
  );
};

/**
 * 上传通用图片
 * @param file 要上传的文件
 * @returns Promise<ApiResponse<UnifiedFileUploadResult>>
 */
export const uploadGeneralImageApi = (
  file: File
): Promise<ApiResponse<UnifiedFileUploadResult>> => {
  const formData = new FormData();
  formData.append("file", file);

  return http.request<ApiResponse<UnifiedFileUploadResult>>(
    "post",
    "/api/upload/general-image",
    {
      data: formData,
      headers: {
        "Content-Type": "multipart/form-data"
      }
    }
  );
};

/**
 * 上传用户头像（使用统一接口）
 * @param file 要上传的文件
 * @returns Promise<ApiResponse<UnifiedFileUploadResult>>
 */
export const uploadAvatarApi = (
  file: File
): Promise<ApiResponse<UnifiedFileUploadResult>> => {
  return unifiedFileUploadApi(file, FileUploadType.AVATAR);
};

/**
 * 文件验证接口
 * @param file 要验证的文件
 * @param type 文件类型
 * @returns Promise<ApiResponse<boolean>>
 */
export const validateFileApi = (
  file: File,
  type: FileUploadType
): Promise<ApiResponse<boolean>> => {
  const formData = new FormData();
  formData.append("file", file);
  formData.append("type", type);

  return http.request<ApiResponse<boolean>>("post", "/api/upload/validate", {
    data: formData,
    headers: {
      "Content-Type": "multipart/form-data"
    }
  });
};

/**
 * 删除文件接口
 * @param path 文件相对路径
 * @param type 文件类型
 * @returns Promise<ApiResponse<null>>
 */
export const deleteFileApi = (
  path: string,
  type: FileUploadType
): Promise<ApiResponse<null>> => {
  return http.request<ApiResponse<null>>("delete", "/api/upload/file", {
    params: { path, type }
  });
};

// ==================== 工具函数 ====================

/**
 * 统一文件上传工具类
 */
export class UnifiedFileUploadUtils {
  /** 支持的图片格式 */
  static readonly SUPPORTED_IMAGE_TYPES = [
    "image/jpeg",
    "image/jpg",
    "image/png",
    "image/gif",
    "image/bmp",
    "image/webp"
  ];

  /** 文件大小限制配置 */
  static readonly FILE_SIZE_LIMITS = {
    [FileUploadType.AVATAR]: 2 * 1024 * 1024, // 2MB
    [FileUploadType.ARTICLE_COVER]: 5 * 1024 * 1024, // 5MB
    [FileUploadType.COMMENT_IMAGE]: 3 * 1024 * 1024, // 3MB
    [FileUploadType.GENERAL_IMAGE]: 10 * 1024 * 1024 // 10MB
  };

  /**
   * 检查文件类型是否支持
   * @param file 文件对象
   * @returns boolean
   */
  static isImageTypeSupported(file: File): boolean {
    return this.SUPPORTED_IMAGE_TYPES.includes(file.type.toLowerCase());
  }

  /**
   * 检查文件大小是否符合要求
   * @param file 文件对象
   * @param type 文件类型
   * @returns boolean
   */
  static isFileSizeValid(file: File, type: FileUploadType): boolean {
    const maxSize = this.FILE_SIZE_LIMITS[type];
    return file.size <= maxSize;
  }

  /**
   * 获取文件大小限制
   * @param type 文件类型
   * @returns number 最大文件大小（字节）
   */
  static getFileSizeLimit(type: FileUploadType): number {
    return this.FILE_SIZE_LIMITS[type];
  }

  /**
   * 格式化文件大小
   * @param bytes 字节数
   * @returns string 格式化后的大小
   */
  static formatFileSize(bytes: number): string {
    if (bytes === 0) return "0 B";

    const k = 1024;
    const sizes = ["B", "KB", "MB", "GB"];
    const i = Math.floor(Math.log(bytes) / Math.log(k));

    return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + " " + sizes[i];
  }

  /**
   * 获取文件扩展名
   * @param filename 文件名
   * @returns string 扩展名
   */
  static getFileExtension(filename: string): string {
    return filename.slice(((filename.lastIndexOf(".") - 1) >>> 0) + 2);
  }

  /**
   * 验证文件
   * @param file 文件对象
   * @param type 文件类型
   * @returns FileValidationResult 验证结果
   */
  static validateFile(file: File, type: FileUploadType): FileValidationResult {
    // 检查文件是否存在
    if (!file) {
      return { valid: false, message: "请选择要上传的文件" };
    }

    // 检查文件类型
    if (!this.isImageTypeSupported(file)) {
      return {
        valid: false,
        message: `不支持的文件类型，请选择 ${this.SUPPORTED_IMAGE_TYPES.join(", ")} 格式的图片`
      };
    }

    // 检查文件大小
    if (!this.isFileSizeValid(file, type)) {
      const maxSize = this.formatFileSize(this.getFileSizeLimit(type));
      return {
        valid: false,
        message: `文件大小超过限制，最大允许 ${maxSize}`
      };
    }

    return { valid: true };
  }

  /**
   * 生成预览URL
   * @param file 文件对象
   * @returns string 预览URL
   */
  static generatePreviewUrl(file: File): string {
    return URL.createObjectURL(file);
  }

  /**
   * 释放预览URL
   * @param url 预览URL
   */
  static revokePreviewUrl(url: string): void {
    URL.revokeObjectURL(url);
  }

  /**
   * 获取文件类型描述
   * @param type 文件类型
   * @returns string 类型描述
   */
  static getFileTypeDescription(type: FileUploadType): string {
    const descriptions = {
      [FileUploadType.AVATAR]: "用户头像",
      [FileUploadType.ARTICLE_COVER]: "文章封面",
      [FileUploadType.COMMENT_IMAGE]: "评论图片",
      [FileUploadType.GENERAL_IMAGE]: "通用图片"
    };
    return descriptions[type] || "未知类型";
  }

  /**
   * 获取存储路径
   * @param type 文件类型
   * @returns string 存储路径
   */
  static getStoragePath(type: FileUploadType): string {
    const paths = {
      [FileUploadType.AVATAR]: "/avatars",
      [FileUploadType.ARTICLE_COVER]: "/articles/covers",
      [FileUploadType.COMMENT_IMAGE]: "/comments/images",
      [FileUploadType.GENERAL_IMAGE]: "/images"
    };
    return paths[type] || "/unknown";
  }
}
